#include <openssl/crypto.h>
#include <vector>
#include <iostream>
#include <digest.cpp>
#include <cipher.cpp>
#include <rand.cpp>
#include <pkey.cpp>
#include <version.cpp>
using namespace std;

int main()
{

    //系统版本和默认参数
    vector<string> versions;
    get_versions(versions);
    cout<<"系统版本和默认参数:"<<endl;
    print_vector(versions);
    cout<<endl;

    //支持的签名算法
    vector<string> digests;
    get_digest_names(digests);
    cout<<"系统支持的签名算法"<<endl;
    print_vector(digests);
    cout<<endl;

    //系统支持的对称密钥算法
    vector<string> ciphers;
    get_cipher_names(ciphers);
    cout<<"系统支持的对称密钥算法"<<endl;
    print_vector(ciphers);
    cout<<endl;

    //系统支持的非对称密钥算法
    vector<string> pkeys;
    get_publickey_algorithm_names(pkeys);
    cout<<"系统支持的非对称密钥算法"<<endl;
    print_vector(pkeys);
    cout<<endl;

    //sm3
    auto ctx = new_digest_context("SM3"); // 加解密上下文环境
    unsigned char c[] = "a"; 
    unsigned char c1[] = "bc";
    update_md_ctx(ctx, c);
    update_md_ctx(ctx, c1);

    unsigned char sm3_outbuf[64];
    unsigned int sm3_outlen = 0;
    final_md_ctx(ctx, sm3_outbuf, sm3_outlen);
    cout<<"abc的sm3摘要结果:";
    for(int i =0; i< (int) sm3_outlen; i++)
    {
        cout<<(int)sm3_outbuf[i];
    }
    cout<<endl<<endl;;
    free_md_ctx(ctx);


    //sm4
    int sm4_keylen = get_cipher_key_length("SMS4");
    unsigned char sm4_key[sm4_keylen];
    generate_random(sm4_key, sm4_keylen);

    int ivlen = get_cipher_iv_length("SMS4");
    unsigned char iv[ivlen];//初始向量
    generate_random(iv, ivlen);

    auto sm4_cipher = new_cipher_context("SMS4", sm4_key, iv, true);
    const unsigned char* sm4_in = (unsigned char*)(char*)"hello";

    int sm4_outlen = get_ciper_update_out_length(sm4_cipher, sm4_in, 5);
    unsigned char sm4_out[sm4_outlen];

    update_cipher_ctx(sm4_cipher, sm4_in, 5 ,sm4_out, sm4_outlen); 
    
    int outlen2 = get_cipher_final_block_size(sm4_cipher);
    unsigned char out2[outlen2];

    final_cipher_ctx(sm4_cipher, out2, sm4_outlen);
    free_cipher_ctx(sm4_cipher);
    cout<<"hello的加密结果: ";
    print_unsigned_char(out2, sm4_outlen);

    auto decryptor = new_cipher_context("SMS4", sm4_key, iv, false);
    int outlen3 = get_ciper_update_out_length(decryptor, out2,sm4_outlen);
    cout<<"outlen3"<<outlen3<<endl;
    unsigned char out3[outlen3];
    int out_len = 0;
    
    update_cipher_ctx(decryptor, out2,sm4_outlen ,out3, out_len);
    unsigned char out4[outlen2];
    
    final_cipher_ctx(decryptor, out4, sm4_outlen);
    cout<<"解密结果: ";
    free_cipher_ctx(decryptor);
    cout<<endl;


    //sm2
    vector<pair<string, string>> params;
    pair<string,string> p1("ec_paramgen_curve", "sm2p256v1");
    pair<string,string> p2("ec_param_enc", "named_curve");
    params.push_back(p1);
    params.push_back(p2);
    EVP_PKEY* pri = generate_private_key("EC", params);

    char* p;
    string sm2skpem = get_pem(pri, "SMS4", "1");
    cout<<"sm2skpem:"<<endl<<sm2skpem<<endl;;
    string sm2sktxt = get_text(pri);
    cout<<"sm2sktxt:"<<endl<<sm2sktxt<<endl;
    string sm2pkpem = get_public_key_pem(pri);
    cout<<"sm2pkpem"<<endl<<sm2pkpem<<endl;

    EVP_PKEY* pub = new_public_key_from_pem(sm2pkpem.c_str());
    string sm2pktxt = get_text(pub);
    sm2pkpem = get_pem(pub);
    cout<<"sm2pktxt"<<endl<<sm2pktxt<<endl;
    cout<<"sm2pkpem"<<endl<<sm2skpem<<endl;

    unsigned char out[64];
    size_t outlen = 64;
    compute_SM2_IDDigest(pub, "1234567812345678", out, outlen);
    cout<<"compute_SM2_IDDigest: ";
    print_unsigned_char(out, outlen);

    unsigned char* msg = (unsigned char*)(char*)"message";
    unsigned char sig[2048];
    size_t outlength;
    sign(pri, "sm2sign", msg, nullptr, sig, outlength); 
    cout<<"message签名结果:";
    print_unsigned_char(sig, outlength);

    cout<<get_char_length(sig)<<endl;

    unsigned char* msg0 = (unsigned char*)(char*)"message";
    bool result = verify(pub,"sm2sign", msg0, sig, outlength,nullptr);
    cout<<"message 的验签:"<<result<<endl;
    cout<<endl;

    const char* sm2encalg = "sm2encrypt-with-sm3";
    unsigned char sm2ciphertext[2048];
    encrypt(pub, sm2encalg, msg, nullptr, sm2ciphertext, outlength);
    cout<<"message的加密结果为:";
    print_unsigned_char(sm2ciphertext, outlength);

    unsigned char sm2plaintext[2048];
    size_t outlength2;
    decrypt(pri, sm2encalg, sm2ciphertext, outlength, NULL,sm2plaintext, outlength2);
    cout<<"message的解密结果为:";
    for( int i =0 ; i< outlength2 ; i++)
    {
        cout<<sm2plaintext[i];
    }
    cout<<endl;

    free_pkey(pri);
    free_pkey(pub);
}